package com.jack.helloworld.util;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Point;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.view.Display;
import android.view.WindowManager;

import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;


/**
 * Created by xiaojian.fu on 2017/6/8.
 */
public class DeviceInfoUtil {

    private static String mImei;
    private static String mImeiWithoutBase64;
    private static String mMac;
    private static String mAndroidId;
    private static String mDevicePixels;

    /**
     * 获取IMEI，需要权限：android.permission.READ_PHONE_STATE （dangerous permission）
     *
     * @param context
     * @return String
     */
    public static String initIMEI(Context context) {
        if (StringUtils.isNotBlank(mImei)) {
            return mImei;
        }
        mImei = (String) SharedPreferenceHelper.read(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_IMEI, SharedPreferenceHelper.STRING_VALUE);
        Logger.d("DeviceInfoUtil:Preference-mImei:" + mImei);
        if (StringUtils.isNotBlank(mImei)) {
            return mImei;
        }
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null)
            return null;
        //6.0权限问题
        if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)) {
            if ((tm.getDeviceId() == null || "".equals(tm.getDeviceId())) && (tm.getSubscriberId() == null || "".equals(tm.getSubscriberId()))) {
                String temp = getMacAddress(context);
                Logger.d("DeviceInfoUtil:getMacAddress-mImei:" + temp);
                if (temp == null || "".equals(temp)) {
                    temp = getAndroidID(context);
                    Logger.d("DeviceInfoUtil:getAndroidID-mImei:" + temp);
                }
                mImei = Base64.encode(temp);
            } else {
                mImei = Base64.encode(tm.getDeviceId());
                Logger.d("DeviceInfoUtil:getDeviceId-mImei:" + mImei);
                if (StringUtils.isNotBlank(mImei)) {
//                    SharedPreferenceHelper.write(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_IMEI, mImei);
                }
            }
        }
        return mImei;
    }

    public static String getIMSI(Context context) {
        if (context == null) {
            return "";
        }
        try {
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            //获取IMSI号
            String imsi;
            if (telephonyManager != null && ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                imsi = telephonyManager.getSubscriberId();
            } else {
                imsi = "";
            }
            Logger.d("DeviceInfoUtil:getIMSI-imsi:" + imsi);
            return imsi;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String initIMEIWithoutBase64(Context context) {
        if (StringUtils.isNotBlank(mImeiWithoutBase64)) {
            return mImeiWithoutBase64;
        }
        mImeiWithoutBase64 = (String) SharedPreferenceHelper.read(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_IMEI_WITHOUT_BASE64, SharedPreferenceHelper.STRING_VALUE);
        if (StringUtils.isNotBlank(mImeiWithoutBase64)) {
            return mImeiWithoutBase64;
        }
        TelephonyManager tm = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null)
            return null;
        //6.0权限问题
        if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)) {

            boolean deviceIdAndSubscriberIdIsNull = (tm.getDeviceId() == null || "".equals(tm.getDeviceId())) && (tm.getSubscriberId() == null || "".equals(tm.getSubscriberId()));
            if (deviceIdAndSubscriberIdIsNull) {
                mImeiWithoutBase64 = getMacAddress(context);
                Logger.d("DeviceInfoUtil:getMacAddress-mImeiWithoutBase64:" + mImeiWithoutBase64);
                if (mImeiWithoutBase64 == null || "".equals(mImeiWithoutBase64)) {
                    mImeiWithoutBase64 = getAndroidID(context);
                }
            } else {
                mImeiWithoutBase64 = tm.getDeviceId();
                Logger.d("DeviceInfoUtil:getDeviceId-mImeiWithoutBase64:" + mImeiWithoutBase64);
                if (StringUtils.isNotBlank(mImeiWithoutBase64)) {
//                    SharedPreferenceHelper.write(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_IMEI_WITHOUT_BASE64, mImeiWithoutBase64);
                }
            }
        }
        return mImeiWithoutBase64;
    }

    /**
     * 获取MAC地址，需要权限: android.permission.ACCESS_WIFI_STATE
     *
     * @param context
     * @return String
     */
    public static String getMacAddress(Context context) {
        return getMacAddress(context, true, false);
    }

    /**
     * @param removeTitle 是否去掉封号
     * @param toUpperCase 是否大写
     */

    public static String getMacAddress(Context context, boolean removeTitle, boolean toUpperCase) {
        String mac;
        if (StringUtils.isNotBlank(mMac)) {
            mac = mMac;
        } else {
            mMac = (String) SharedPreferenceHelper.read(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_MAC, SharedPreferenceHelper.STRING_VALUE);
            Logger.d("DeviceInfoUtil:Preference-mMac:" + mMac);
            if (StringUtils.isNotBlank(mMac)) {
                mac = mMac;
            } else {
                mMac = getMacAddressByWifi(context);
                Logger.d("DeviceInfoUtil:getMacAddressByWifi-mMac:" + mMac);
                String str = "";
                if (removeTitle) {
                    if (StringUtils.isNotBlank(mMac)) {
                        str = mMac.replace(":", "");
                    }
                    if (str.matches("(\\p{XDigit})\\1{11}") || str.endsWith("020000000000")) {
                        mMac = reGetMacAddress();
                    }
                } else {
                    if (StringUtils.isNotBlank(mMac)) {
                        str = mMac;
                    }
                    if (str.matches("(\\p{XDigit})\\1{16}") || str.endsWith("02:00:00:00:00:00")) {
                        mMac = reGetMacAddress();
                    }
                }
                if (StringUtils.isNotBlank(mMac)) {
//                    SharedPreferenceHelper.write(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_MAC, mMac);
                }
                mac = mMac;
            }
        }

        if (StringUtils.isNotBlank(mac)) {
            if (toUpperCase) {
                mac = mac.toUpperCase();
            } else {
                mac = mac.toLowerCase();
            }
        }
        return mac;
    }

    //系统获取mac地址
    private static String getMacAddressByWifi(Context context) {
        String localMac = null;
        WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager == null) {
            return null;
        }
        WifiInfo wifiConnInfo = null;
        if (wifiManager.getWifiState() != WifiManager.WIFI_STATE_UNKNOWN) {
            try {
                wifiConnInfo = wifiManager.getConnectionInfo();
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
            if (wifiConnInfo == null)
                return null;
            localMac = wifiConnInfo.getMacAddress();
        }
        return localMac;
    }

    public static String reGetMacAddress() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return getMacAddress();
        } else {
            return getMacOnFile();
        }
    }

    /**
     * 根据IP地址获取MAC地址
     *
     * @return
     */
    public static String getMacAddress() {
        String strMacAddr = null;
        try {
            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
            if (enumeration == null) {
                return null;
            }
            while (enumeration.hasMoreElements()) {
                NetworkInterface netInterface = enumeration.nextElement();
                if (netInterface.getName().equals("wlan0")) {
                    byte[] b = netInterface.getHardwareAddress();
                    StringBuffer buffer = new StringBuffer();
                    for (int i = 0; i < b.length; i++) {
                        if (i != 0) {
                            buffer.append(':');
                        }
                        String str = Integer.toHexString(b[i] & 0xFF);
                        buffer.append(str.length() == 1 ? 0 + str : str);
                    }
                    strMacAddr = buffer.toString();
                    break;
                }
            }
        } catch (Exception e) {

        }
        Logger.d("DeviceInfoUtil:reGetMacAddress-getMacAddress-mMac:" + strMacAddr);
        return strMacAddr;
    }

    /**
     * 获取移动设备本地IP
     *
     * @return
     */
    private static InetAddress getLocalInetAddress() {
        InetAddress ip = null;
        try {
            // 列举
            Enumeration<NetworkInterface> en_netInterface = NetworkInterface
                    .getNetworkInterfaces();
            while (en_netInterface.hasMoreElements()) {// 是否还有元素
                NetworkInterface ni = (NetworkInterface) en_netInterface
                        .nextElement();// 得到下一个元素
                Enumeration<InetAddress> en_ip = ni.getInetAddresses();// 得到一个ip地址的列举
                while (en_ip.hasMoreElements()) {
                    ip = en_ip.nextElement();
                    if (!ip.isLoopbackAddress()
                            && ip.getHostAddress().indexOf(":") == -1)
                        break;
                    else
                        ip = null;
                }

                if (ip != null) {
                    break;
                }
            }
        } catch (SocketException e) {

            e.printStackTrace();
        }
        return ip;
    }

    /**
     * 6.0获取mac
     *
     * @return String
     */
    private static String getMacOnFile() {
        String mac = null;
        String wifiDir = MySystemProperties.get("wifi.interface");
        File path = new File("/sys/class/net/" + wifiDir + "/address");
        int count = 20;// 20*200=4s
        while (!path.exists() && count-- > 0) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException ignored) {
            }
        }
        if (!path.exists()) {
            return null;
        }
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(path);
            byte[] buff = new byte[32];
            int len = fis.read(buff);
            mac = new String(buff, 0, len).trim()/*.replace(":", "")*/.toLowerCase();
        } catch (FileNotFoundException ignored) {
        } catch (IOException ignored) {
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException ignored) {
                }
            }
        }
        Logger.d("DeviceInfoUtil:reGetMacAddress-getMacOnFile-mMac:" + mMac);
        return mac;
    }

    public static int getSimType(Context context) {
        int type = 0;
        TelephonyManager telManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String operator = telManager.getSimOperator();
        if (operator != null) {
            if (operator.equals("46000") || operator.equals("46002") || operator.equals("46007")) {
                //中国移动
                type = 1;
            } else if (operator.equals("46001") || operator.equals("46006")) {
                //中国联通
                type = 2;
            } else if (operator.equals("46003") || operator.equals("46011")) {
                //中国电信
                type = 3;
            }
        }
        return type;
    }

    public static String getSimTypeForAdMate(Context context) {
        String type = "";
        TelephonyManager telManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String operator = telManager.getSimOperator();
        if (operator != null) {
            if (operator.equals("46000") || operator.equals("46002")) {
                //中国移动
                type = "46000";
            } else if (operator.equals("46001")) {
                //中国联通
                type = "46001";
            } else if (operator.equals("46003") || operator.equals("46011")) {
                //中国电信
                type = "46003";
            }
        }
        return type;
    }

    /**
     * 判断是否包含SIM卡
     *
     * @return 状态
     */
    public static boolean hasSimCard(Context context) {
        TelephonyManager telMgr = (TelephonyManager)
                context.getSystemService(Context.TELEPHONY_SERVICE);
        int simState = telMgr.getSimState();
        boolean result = true;
        switch (simState) {
            case TelephonyManager.SIM_STATE_ABSENT:
                result = false; // 没有SIM卡
                break;
            case TelephonyManager.SIM_STATE_UNKNOWN:
                result = false;
                break;
        }
        return result;
    }

    /**
     * @param context
     * @return 获取分辨率，高x宽度（1920x1080）
     */
    public static String getDevicePixels(Context context) {
        if (StringUtils.isNotBlank(mDevicePixels)) {
            return mDevicePixels;
        }
        mDevicePixels = (String) SharedPreferenceHelper.read(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_DEVICE_PIXELS, SharedPreferenceHelper.STRING_VALUE);
        if (StringUtils.isNotBlank(mDevicePixels)) {
            return mDevicePixels;
        }
        int height = getDeviceHeightPixels(context);
        int width = getDeviceWidthPixels(context);
        if (height > 0 && width > 0) {
            mDevicePixels = height + "x" + width;
            if (StringUtils.isNotBlank(mDevicePixels)) {
//                SharedPreferenceHelper.write(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_DEVICE_PIXELS, mDevicePixels);
            }
        } else {
            return "";
        }
        return mDevicePixels;
    }

    /**
     * 获得设备屏幕宽度 单位像素
     */
    public static int getDeviceWidthPixels(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    /**
     * 获得设备屏幕高度 单位像素
     */
    public static int getDeviceHeightPixels(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;
    }

    public static int getDeviceDpi(Context context) {
        return context.getResources().getDisplayMetrics().densityDpi;
    }

    public static int getDeviceRealDpi(Context context) {
        float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
        int densityDpi = context.getResources().getDisplayMetrics().densityDpi;
        float xdpi = context.getResources().getDisplayMetrics().xdpi;
        float ydpi = context.getResources().getDisplayMetrics().ydpi;

        int width = 0;
        int height = 0;

        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Point point = new Point();
            windowManager.getDefaultDisplay().getRealSize(point);
            width = point.x;
            height = point.y;
        } else {
            Display display = windowManager.getDefaultDisplay();
            width = display.getWidth();
            height = display.getHeight();
        }

        // 这样可以计算屏幕的物理尺寸
        float widthPhySqr = (width / xdpi) * (width / xdpi);
        float heightPhySqr = (height / ydpi) * (height / ydpi);

        float screenSize = (float) Math.sqrt(widthPhySqr + heightPhySqr);
        int ppi = (int) ((Math.sqrt(width * width + height * height)) / screenSize);

        //        Log.i("ppi===","densityDpi="+densityDpi+" ydpi="+ydpi+" xdpi="+xdpi+" scaledDensity="+scaledDensity
        //                +" width="+width+" height="+height+" screenSize="+screenSize+" ppi="+ppi
        //                +" device="+ Build.DEVICE+" display="+Build.DISPLAY);

        return ppi;
    }

    /**
     * Android ID
     * 通常被认为不可信，因为它有时为null。开发文档中说明了：这个ID会改变如果进行了出厂设置。并且，如果某个
     * Andorid手机被Root过的话，这个ID也可以被任意改变。无需任何许可。
     */
    public static String getAndroidID(Context context) {
        if (StringUtils.isNotBlank(mAndroidId)) {
            return mAndroidId;
        }
        mAndroidId = (String) SharedPreferenceHelper.read(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_ANDROID_ID, SharedPreferenceHelper.STRING_VALUE);
        if (StringUtils.isNotBlank(mAndroidId)) {
            return mAndroidId;
        }
        mAndroidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        if (StringUtils.isNotBlank(mAndroidId)) {
//            SharedPreferenceHelper.write(context, Constants.SP_DEVICE_INFO, Constants.SP_DEVICE_INFO_KEY_ANDROID_ID, mAndroidId);
        }
        Logger.d("DeviceInfoUtil:getAndroidID-mAndroidId:" + mAndroidId);
        return mAndroidId;
    }

    public static String getSerial(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return "";
            }
            return Build.getSerial();
        } else {
            return Build.SERIAL;
        }
    }

    /**
     * 获取设备类型
     *
     * @param context
     * @return
     */
    private static String getDeviceType(Context context) {
        if (isTablet(context)) {
            return "AndroidHD";
        } else {
            return "Android";
        }
    }

    /**
     * 判断当前设备是手机还是平板，代码来自 Google I/O App for Android
     *
     * @return 平板返回 True，手机返回 False
     */
    public static boolean isTablet(Context context) {
        boolean isTable = false;
        try {
            isTable = (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
        } catch (Exception ignored) {
        }
        return isTable;
    }

    /**
     * 获取注册时需要的imei和imsi
     * imeiAndImsiParams[0] 为imei,imeiAndImsiParams[1] 为imsi
     *
     * @param context
     * @return
     */
    @NonNull
    public static String[] getImeiAndImsi(Context context) {
        String[] imeiAndImsiParams = new String[2];
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        //6.0权限问题
        if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)) {

            if ((tm.getDeviceId() == null || "".equals(tm.getDeviceId())) && (tm.getSubscriberId() == null || "".equals(tm.getSubscriberId()))) {
                imeiAndImsiParams[0] = Base64.encode(initIMEI(context));
                imeiAndImsiParams[1] = Base64.encode(tm.getSubscriberId());
            } else {
                imeiAndImsiParams[0] = Base64.encode(tm.getDeviceId());
                imeiAndImsiParams[1] = Base64.encode(tm.getSubscriberId());
            }
        }
        for (int i = 0; i < imeiAndImsiParams.length; i++) {
            if (imeiAndImsiParams[i] == null) {
                imeiAndImsiParams[i] = "";
            }
        }
        return imeiAndImsiParams;
    }

    public static String getDeviceMd5() {
        StringBuilder sb = new StringBuilder();
        sb.append(Build.FINGERPRINT).append("/") //设备指纹（同型号同批次值一样） 示例：honor/FRD-AL00/HWFRD:6.0/HUAWEIFRD-AL00/C00B171:user/release-keys
                .append(Build.HARDWARE).append("/") //硬件名称 示例：hi3650
                .append(Build.BOARD).append("/") //主板 示例：FRD-AL00
                .append(Build.BRAND).append("/") //系统定制商 示例：honor
                .append(Build.DEVICE).append("/") //设备参数 示例：HWFRD
                .append(Build.HOST).append("/") //示例：huawei-RH2288H-V2-12L
                .append(Build.ID).append("/") //修订版本列表 示例：HUAWEIFRD-AL00
                .append(Build.MANUFACTURER).append("/") //产品/硬件的制造商 示例：HUAWEI
                .append(Build.MODEL).append("/") //示例：FRD-AL00
                .append(Build.PRODUCT).append("/") //产品的名称 示例：FRD-AL00
                .append(Build.DISPLAY); //用于向用户显示的生成 ID 字符串 示例：FRD-AL00C00B171
        return sb.toString();
    }

    /**
     * 检测是否为华为手机
     * 只要返回不是""，则是EMUI版本 如果emuiVerion不为空，即表示为华为设备。
     *
     * @return
     */
    public static boolean isHwPhone() {
        Class<?>[] clsArray = new Class<?>[]{String.class};
        Object[] objArray = new Object[]{"ro.build.version.emui"};
        try {
            Class<?> SystemPropertiesClass = Class.forName("android.os.SystemProperties");
            Method get = SystemPropertiesClass.getDeclaredMethod("get", clsArray);
            String emuiVerion = (String) get.invoke(SystemPropertiesClass, objArray);
            if (!TextUtils.isEmpty(emuiVerion)) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
